package com.aaa.hookdemo.hook_click_listener;

import android.util.Log;
import android.view.View;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class HookOnClickListener {
    private static final String TAG = "HookOnClickListener";

    public void doHook(View view) {
        try {
            // 第一步：反射得到 ListenerInfo 对象
            Method getListenerInfo = View.class.getDeclaredMethod("getListenerInfo");
            getListenerInfo.setAccessible(true);
            Object listenerInfo = getListenerInfo.invoke(view); // 反射执行方法

            // 第二步：得到原始的 OnClickListener事件方法
            Class<?> listenerInfoClz = Class.forName("android.view.View$ListenerInfo");
            Field mOnClickListener = listenerInfoClz.getDeclaredField("mOnClickListener");
            mOnClickListener.setAccessible(true);
            View.OnClickListener originOnClickListener = (View.OnClickListener) mOnClickListener.get(listenerInfo); // 反射获取属性

            // 第三步：用 Hook代理类 替换原始的 OnClickListener
            View.OnClickListener hookedOnClickListener = new HookedClickListenerProxy(originOnClickListener);
            mOnClickListener.set(listenerInfo, hookedOnClickListener); // 反射修改属性值
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

class HookedClickListenerProxy implements View.OnClickListener {
    private static final String TAG = "HookedClickListenerProx";
    private View.OnClickListener origin;

    public HookedClickListenerProxy(View.OnClickListener origin) {
        this.origin = origin;
    }

    @Override
    public void onClick(View v) {
        Log.d(TAG, "do before onClick: ");
        if (origin != null) {
            origin.onClick(v);
        }
        Log.d(TAG, "do after onClick: ");
    }

}
